﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Serilog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TMI85303.Utils;

namespace TMI85303.UI.UserControls
{
    /// <summary>
    /// TrimControl.xaml 的交互逻辑
    /// </summary>
    public partial class TrimControl : UserControl
    {
        public TrimControl()
        {
            InitializeComponent();
        }

        private void PasswordBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            e.Handled = !e.Text.All(IsHexadecimal);
        }

        private void PasswordBox_Pasting(object sender, DataObjectPastingEventArgs e)
        {
            if (e.DataObject.GetDataPresent(typeof(String)))
            {
                string text = (string)e.DataObject.GetData(typeof(String));
                // 检查粘贴的文本是否为十六进制
                if (!text.All(IsHexadecimal))
                {
                    e.CancelCommand();
                }
            }
            else
            {
                e.CancelCommand();
            }
        }
        private bool IsHexadecimal(char c)
        {
            // 检查字符是否在十六进制字符范围内
            return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
        }
    }

    public partial class TrimVM : ObservableObject
    {
        [ObservableProperty]
        private int oCLOffset = 0;

        [ObservableProperty]
        private int oCLOffsetShow = 0;

        [ObservableProperty]
        private int oCLGain = 0;
        [ObservableProperty]
        private int oCLGainShow = 0;

        [ObservableProperty]
        private int lSDDrive = 0;
        [ObservableProperty]
        private int lSDDriveShow = 0;

        [ObservableProperty]
        private OcpAnalogDelay ocpAnalogDelayVal = OcpAnalogDelay._560ns;

        [ObservableProperty]
        private OCLFilter oCLFilterVal = OCLFilter._480_520ns;

        [ObservableProperty]
        private OCL oCLVal = OCL.Enabled;

        [ObservableProperty]
        private NegErr_PosErr negErr_PosErrVal = NegErr_PosErr.Disabled;

        [ObservableProperty]
        private OcpThrSel ocpThrSelVal = OcpThrSel.LOW;

        [ObservableProperty]
        private int pLL = 0;

        [ObservableProperty]
        private int pLLShow = 0;

        [ObservableProperty]
        private int bandgap = 0;

        [ObservableProperty]
        private int bandgapShow = 0;

        [ObservableProperty]
        private int biasCurrent = 0;

        [ObservableProperty]
        private int biasCurrentShow = 0;

        [ObservableProperty]
        private OclBlank oclBlankVal = OclBlank._0_4us;

        [ObservableProperty]
        private OpenLoopVbbComp openLoopVbbCompVal = OpenLoopVbbComp.Enabled;

        [ObservableProperty]
        private Deadtime deadtimeVal = Deadtime._360ns;

        
        private string? passcode = null;
        public string? Passcode
        {
            get => passcode;
            set
            {
                SetProperty(ref passcode, value);
                if (string.IsNullOrWhiteSpace(passcode))
                {
                    password = null;
                }
                else if (int.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var newVal))
                {
                    password = newVal;
                }
                else
                {
                    Log.Information("输入密码为非十六进制数！");
                }
            }
        }

        private int? password = null;


        public TrimVM()
        {

        }

        partial void OnOCLOffsetChanged(int value) => OCLOffsetShow = value;
        partial void OnOCLGainChanged(int value) => OCLGainShow = value;
        partial void OnLSDDriveChanged(int value) => LSDDriveShow = value;
        partial void OnPLLChanged(int value) => PLLShow = value;
        partial void OnBandgapChanged(int value) => BandgapShow = value;
        partial void OnBiasCurrentChanged(int value) => BiasCurrentShow = value;

        [RelayCommand]
        private void ReadFromShadow()
        {
            SetReg92(ReadWrite.ReadReg(92, 2));
            SetReg95(ReadWrite.ReadReg(95, 2));
        }

        [RelayCommand]
        private void ReadFromEEPROM()
        {
            Log.Information(" 读EEPROM:\r\n");
            SetReg92(ReadWrite.ReadReg(28, 2));
            SetReg95(ReadWrite.ReadReg(31,2));
        }

        [RelayCommand]
        private void Write2Shadow()
        {
            ReadWrite.WriteReg(92, GetWriteReg92(), 2);
            ReadWrite.WriteReg(95, GetWriteReg95(), 2);
        }

        [RelayCommand]
        private void Write2EEPROM()
        {
            if (MessageBox.Show("请确定你是否要修改Trim?", "Trim", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.Cancel)
            {
                Log.Information(" 取消Trim写操作\r\n");
                return;
            }
            ReadWrite.WriteEE28And31(28, GetWriteReg92());
            ReadWrite.WriteEE28And31(31, GetWriteReg95());
        }

        [RelayCommand]
        private void UnlockTrim() => ReadWrite.unlockTrim();

        [RelayCommand]
        private void LockTrim() => ReadWrite.lockTrim();

        [RelayCommand]
        private void LockEE7()
        {
            if (password == null)
            {
                Log.Information("请输入正确的十六进制数");
                return;
            }
            ReadWrite.WriteEE(7, (int)password);
        }

        [RelayCommand]
        private void UnlockReg159()
        {
            if (password == null)
            {
                Log.Information("请输入正确的十六进制数");
                return;
            }
            ReadWrite.WriteReg(7, (int)password, 2);
        }

        private int GetWriteReg92()
        {
            int reg92Bit15 = OcpThrSelVal == OcpThrSel.LOW ? 0 : 1;
            int reg92Bit14 = NegErr_PosErrVal == NegErr_PosErr.Enabled ? 0 : 1;
            int reg92Bit13 = OCLVal == OCL.Enabled ? 0 : 1;
            int reg92Bit12 = OCLFilterVal == OCLFilter._480_520ns ? 0 : 1;
            int reg92Bit11 = OcpAnalogDelayVal == OcpAnalogDelay._560ns ? 0 : 1;
            int reg92Bit8_10 = LSDDrive;
            int reg92Bit4_7 = OCLGain;
            int reg92Bit0_3 = OCLOffset;

            return (reg92Bit15 << 15) | (reg92Bit14 << 14) | (reg92Bit13 << 13) | (reg92Bit12 << 12) |
              (reg92Bit11 << 11) | (reg92Bit8_10 << 8) | (reg92Bit4_7 << 4) | reg92Bit0_3;
        }

        private int GetWriteReg95()
        {
            int reg95Bit15 = DeadtimeVal == Deadtime._360ns ? 0 : 1;
            int reg95Bit14 = OpenLoopVbbCompVal == OpenLoopVbbComp.Enabled ? 0 : 1;
            int reg95Bit12_13 = OclBlankVal switch
            {
                OclBlank._0_4us => 00,
                OclBlank._0_72us => 01,
                OclBlank._1_04us => 10,
                OclBlank.OCPDisabled => 11,
                _ => 11
            };
            int reg95Bit9_11 = BiasCurrent;
            int reg95Bit6_8 = Bandgap;
            int reg95Bit0_5 = PLL;
            return (reg95Bit15 << 15) | (reg95Bit14 << 14) | (reg95Bit12_13 << 12) | (reg95Bit9_11 << 9) |
              (reg95Bit6_8 << 6) | reg95Bit0_5;//2023.8.3 revise
        }

        private void SetReg92(int regData92)
        {
            int reg92Bit15 = (regData92 & 0x8000) >> 15;
            int reg92Bit14 = (regData92 & 0x4000) >> 14;
            int reg92Bit13 = (regData92 & 0x2000) >> 13;
            int reg92Bit12 = (regData92 & 0x1000) >> 12;
            int reg92Bit11 = (regData92 & 0x0800) >> 11;
            int reg92Bit8_10 = (regData92 & 0x0700) >> 8;
            int reg92Bit4_7 = (regData92 & 0x00F0) >> 4;
            int reg92Bit0_3 = (regData92 & 0x000F);

            OcpThrSelVal = reg92Bit15 == 0 ? OcpThrSel.LOW : OcpThrSel.HIGH;
            NegErr_PosErrVal = reg92Bit14 == 0 ? NegErr_PosErr.Enabled : NegErr_PosErr.Disabled;
            OCLVal = reg92Bit13 == 0 ? OCL.Enabled : OCL.Disabled;
            OCLFilterVal = reg92Bit12 == 0 ? OCLFilter._480_520ns : OCLFilter._640_680ns;
            OcpAnalogDelayVal = reg92Bit11 == 0 ? OcpAnalogDelay._560ns : OcpAnalogDelay._440ns;
            LSDDrive = reg92Bit8_10;
            OCLGain = reg92Bit4_7;
            OCLOffset = reg92Bit0_3;
        }

        private void SetReg95(int regData95)
        {
            int reg95Bit15 = (regData95 & 0x8000) >> 15;
            int reg95Bit14 = (regData95 & 0x4000) >> 14;
            int reg95Bit12_13 = (regData95 & 0x3000) >> 12;
            int reg95Bit9_11 = (regData95 & 0x0E00) >> 9;
            int reg95Bit6_8 = (regData95 & 0x01C0) >> 6;
            int reg95Bit0_5 = (regData95 & 0x003F);

            DeadtimeVal = reg95Bit15 == 0 ? Deadtime._360ns: Deadtime._480ns;
            OpenLoopVbbCompVal = reg95Bit14 == 0 ? OpenLoopVbbComp.Enabled : OpenLoopVbbComp.Disabled;
            OclBlankVal = reg95Bit12_13 switch
            {
                0  => OclBlank._0_4us,
                01 => OclBlank._0_72us,
                10 => OclBlank._1_04us,
                11 => OclBlank.OCPDisabled,
                _ => OclBlank.OCPDisabled,
            };
            if (reg95Bit9_11 < 8) BiasCurrent = reg95Bit9_11;
            if (reg95Bit6_8 < 8) Bandgap = reg95Bit6_8;
            if (reg95Bit0_5 < 64) PLL = reg95Bit0_5;
        }
    }


}
